package pir

import (
	"bufio"
	"encoding/csv"
	"encoding/gob"
	"fmt"
	"io"
	"os"
	"strings"
)

func SaveLargeCSV(filename string, lines []string, batchSize int) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(bufio.NewWriter(file)) // 带缓冲的writer
	defer writer.Flush()

	batch := make([][]string, 0, batchSize)

	for _, line := range lines {
		record := strings.Split(line, ",")
		batch = append(batch, record)

		if len(batch) == batchSize {
			if err := writer.WriteAll(batch); err != nil {
				return err
			}
			batch = batch[:0] // 清空批次，复用slice
		}
	}

	// 写入剩余不足一个批次的行
	if len(batch) > 0 {
		if err := writer.WriteAll(batch); err != nil {
			return err
		}
	}

	return nil
}

func SaveLinesToCSV(filename string, lines []string) error {
	file, err := os.Create(filename) // 创建（或覆盖）文件
	if err != nil {
		return err
	}
	defer file.Close()

	writer := csv.NewWriter(file)
	defer writer.Flush()

	for _, line := range lines {
		// 将单行字符串按逗号拆分成字段切片
		record := strings.Split(line, ",")
		if err := writer.Write(record); err != nil {
			return err
		}
	}

	return nil
}
func ReadCSVLinesAsStrings(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	records, err := reader.ReadAll()
	if err != nil {
		return nil, err
	}

	var lines []string
	for _, row := range records {
		line := strings.Join(row, ",") // 按逗号连接每一行字段
		lines = append(lines, line)
	}
	return lines, nil
}

func ReadLargeCSVLines(filename string) ([]string, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	reader := csv.NewReader(bufio.NewReader(file))

	var lines []string
	for {
		record, err := reader.Read()
		if err == io.EOF {
			break // 读取完成
		}
		if err != nil {
			return nil, err // 解析错误
		}

		// 将当前行拼接为一个字符串
		line := strings.Join(record, ",")
		lines = append(lines, line)
	}

	return lines, nil
}

// Save 方法将矩阵保存到指定的文件
func (m *Matrix) Save(filename string) error {
	// 打开文件进行写入
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	// 创建一个新的 gob 编码器
	encoder := gob.NewEncoder(file)

	// 编码并写入数据
	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

// Load 方法从文件加载矩阵
func (m *Matrix) Load(filename string) error {
	// 打开文件进行读取
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	// 创建一个新的 gob 解码器
	decoder := gob.NewDecoder(file)

	// 解码并加载数据
	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *Msg) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *Msg) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *MsgSlice) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *MsgSlice) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *State) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *State) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *Params) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *Params) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *DBinfo) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *DBinfo) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *Database) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *Database) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *Vec) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *Vec) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}

func (m *Indexs) Save(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return fmt.Errorf("failed to create file: %w", err)
	}
	defer file.Close()

	encoder := gob.NewEncoder(file)

	err = encoder.Encode(m)
	if err != nil {
		return fmt.Errorf("failed to encode matrix: %w", err)
	}

	return nil
}

func (m *Indexs) Load(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	decoder := gob.NewDecoder(file)

	err = decoder.Decode(m)
	if err != nil {
		return fmt.Errorf("failed to decode matrix: %w", err)
	}

	return nil
}
